package app.comet

import app.Mode
import app.agent.RootAgent
import app.agent.scatchpad.ScratchPadLocator
import app.server.services.ServiceFactory
import app.server._
import ServiceFactory.serverActor
import im.mange.jetboot.js.JsCmdFactory
import JsCmdFactory._
import net.liftweb.http.js.JsCmds.After
import net.liftweb.util.TimeHelpers._
import net.liftweb.http.js.JsCmds.After
import app.server.ServicesResponse
import app.server.SystemsResponse
import app.agent.RootAgent
import app.server.SystemsRequest
import app.server.ServicesRequest
import app.agent.tests.TestsLocator

//icons:
// - ? = playground/scratch pad
// - list alt = ?
// - book = suite
// - play = run
// - road = release?
// - ? = stats
// - ? = spec
// - time = perf?

//TODO: push probeProviderActor into the Agent (and rename the agent)
class AppCometActor extends MessageCapturingCometActor with ExceptionHandlingActor {
  private var root: RootAgent = _

  override def render = {
    root = RootAgent(AppCometActor.this)
    serverActor() ! Init
//    serverActor() ! Subscribe(this)
    root.render
  }

  def handleLowPriority(any: Any) {
    any match {
//      case i:Init ⇒ partialUpdate(root.onInit(i.allProbes))
      case RequestSystems ⇒ partialUpdate(onRequestSystems)
      case RequestServices ⇒ partialUpdate(onRequestServices)
      case RequestTests ⇒ partialUpdate(onRequestTests)
      case ViewTest(id) ⇒ partialUpdate(onViewTest(id))
      case RunTest(id) ⇒ partialUpdate(onRunTest(id))
      case StopTest(id) ⇒ partialUpdate(onStopTest(id))

      case r:SystemsResponse ⇒ partialUpdate(root.onSystemsResponse(r) &
        (if (Mode.isDemo) reveal(ScratchPadLocator.scratchPadAgent) else nothing)
      )

      case r:ServicesResponse ⇒ partialUpdate(root.onServicesResponse(r) &
        (if (Mode.isDemo) reveal(TestsLocator.testsAgent) else nothing)
      )

      case r:TestsResponse ⇒ partialUpdate(root.onTestsResponse(r) //&
//        (if (Mode.isDemo) reveal(ScratchPadLocator.scratchPadAgent) else nothing)
      )

      //TODO: TestLoaded?
      case r:TestContent ⇒ partialUpdate(root.onTestContent(r))
      case r:ValidatedTestRun ⇒ partialUpdate(root.onValidatedTestRun(r))
      case r:StartedTestRun ⇒ partialUpdate(root.onStartedTestRun(r))
      case r:StoppedTestRun ⇒ partialUpdate(root.onStoppedTestRun(r))
      case r:UpdateTestRun ⇒ partialUpdate(root.onUpdateTestRun(r))

      case r:AddSystem ⇒ partialUpdate(root.onAddSystem)

      case e ⇒ handleUnexpectedMessage(this, e)
    }
  }

  //TODO: use 10 seconds for real demo's
  //TODO: put on JsCmdFactory
  private def reveal(id: String) = After(seconds(1), showElement(id))

  override def localShutdown() {
//    serverActor() ! Unsubscribe(this)
    root.onCleanup()
    super.localShutdown()
  }

  //TODO: fireAndForget
  private def onRequestSystems = {
    serverActor() ! SystemsRequest(this)
    nothing
  }

  private def onRequestServices = {
    serverActor() ! ServicesRequest(this)
    nothing
  }

  private def onRequestTests = {
    serverActor() ! TestsRequest(this)
    nothing
  }

  private def onViewTest(testId: String) = {
    serverActor() ! TestView(testId, this)
    nothing
  }

  private def onRunTest(testId: String) = {
    serverActor() ! ScheduleTestRun(testId, this)
    nothing
  }

  private def onStopTest(testRunId: String) = {
    serverActor() ! StopTestRun(testRunId, this)
    nothing
  }
}